package cn.com.bonc.khjy.config;

import cn.com.bonc.khjy.utils.JacksonMapper;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.Cache;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.interceptor.CacheErrorHandler;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisClusterConfiguration;
import org.springframework.data.redis.connection.RedisNode;
import org.springframework.data.redis.connection.RedisPassword;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import redis.clients.jedis.JedisPoolConfig;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

@Configuration
public class RedisConfig extends CachingConfigurerSupport {
    @Value("${spring.redis.host}")
    private String host;
    @Value("${spring.redis.port}")
    private int port;
    @Value("${spring.redis.password}")
    private String password;
    @Value("${spring.redis.pool.max-active}")
    private int maxActive;
    @Value("${spring.redis.pool.max-idle}")
    private int maxIdle;
    @Value("${spring.redis.pool.min-idle}")
    private int minIdle;
    @Value("${spring.redis.pool.max-wait}")
    private int maxWait;
    @Value("${spring.redis.cluster.nodes}")
    private String clusterNodes;
    @Value("${spring.redis.cluster.max-redirects}")
    private int maxRedirects;

    @Value("${epm.redis.single.password}")
    private String singlePwd;

    @Bean
    public JedisConnectionFactory jedisConnectionFactory() {
        JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
        jedisPoolConfig.setMaxTotal(maxActive);
        jedisPoolConfig.setMaxIdle(maxIdle);
        jedisPoolConfig.setMinIdle(minIdle);
        jedisPoolConfig.setMaxWaitMillis(maxWait);
        if(clusterNodes!=null&&clusterNodes.indexOf(",")!=-1){//集群模式配置
            RedisClusterConfiguration redisClusterConfiguration = new RedisClusterConfiguration();
            List<RedisNode> nodeList = new ArrayList<RedisNode>();
            Arrays.asList(clusterNodes.split(",")).forEach(node->{
                nodeList.add(new RedisNode(node.trim().split(":")[0].trim(),Integer.parseInt(node.trim().split(":")[1].trim())));
            });
            redisClusterConfiguration.setClusterNodes(nodeList);
            redisClusterConfiguration.setMaxRedirects(maxRedirects);
            redisClusterConfiguration.setPassword(RedisPassword.of(password));
            JedisConnectionFactory factory = new JedisConnectionFactory(redisClusterConfiguration,jedisPoolConfig);
            factory.afterPropertiesSet();
            return factory;
        }
        else{//单机模式配置
            JedisConnectionFactory factory = new JedisConnectionFactory();
            factory.setPassword(singlePwd);
            factory.setHostName(host);
            factory.setPort(port);
            factory.setPoolConfig(jedisPoolConfig);
            return factory;
        }
    }




    @Bean
    public KeyGenerator cacheKeyGenerator() {
        return (target, method, params) -> {
            StringBuilder sb = new StringBuilder();
            sb.append(target.getClass().getName());
            sb.append(method.getName());
            for (Object obj : params) {
                sb.append(JacksonMapper.INSTANCE.writeObjectToJson(obj).hashCode());
            }
            return sb.toString();
        };
    }



    @Bean
    @Override
    public CacheErrorHandler errorHandler() {
        CacheErrorHandler cacheErrorHandler = new CacheErrorHandler() {
            @Override
            public void handleCacheGetError(RuntimeException e, Cache cache, Object key) {
                System.out.println(key);
            }

            @Override
            public void handleCachePutError(RuntimeException e, Cache cache, Object key, Object value) {
                System.out.println(value);
            }

            @Override
            public void handleCacheEvictError(RuntimeException e, Cache cache, Object key) {

            }

            @Override
            public void handleCacheClearError(RuntimeException e, Cache cache) {

            }
        };
        return cacheErrorHandler;
    }
}
